package com.keste.adf.ui.fwk.util;

import java.sql.Timestamp;

import java.util.Map;

import javax.el.ELContext;

import javax.el.ExpressionFactory;

import javax.el.MethodExpression;
import javax.el.ValueExpression;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

import oracle.adf.model.BindingContext;
import oracle.adf.model.OperationBinding;

import oracle.adf.view.rich.component.rich.RichPopup;
import oracle.adf.view.rich.context.AdfFacesContext;

import oracle.binding.BindingContainer;

import oracle.jbo.ApplicationModule;

import oracle.jbo.domain.Date;

import oracle.jbo.uicli.binding.JUCtrlRangeBinding;
import oracle.jbo.uicli.binding.JUIteratorBinding;

import org.apache.log4j.Logger;
import org.apache.myfaces.trinidad.render.ExtendedRenderKitService;
import org.apache.myfaces.trinidad.util.Service;

public class QuizUtils {
    
    private static final String ONLINE_QUIZ_AM = "OnlineQuizAM";
    
    public QuizUtils() {
        super();
    }
    
    public static FacesContext getFacesContext() {
        FacesContext facesContext;
        facesContext = FacesContext.getCurrentInstance();
        return facesContext;
    }

    public static ELContext getELContext() {
        FacesContext facesContext;
        ELContext elContext;
        facesContext = getFacesContext();
        elContext = facesContext.getELContext();
        return elContext;
    }

    public static ExpressionFactory getExpressionFactory() {
        FacesContext fc;
        ELContext elc;
        ExpressionFactory ef;
        fc = getFacesContext();
        elc = getELContext();
        ef = fc.getApplication().getExpressionFactory();
        return ef;
    }


    public static String getELAsStringWithDefault(String expr, String defaultExpr) {
        return (String)getWithDefault(expr, defaultExpr);
    }

    public static String getELAsString(String expr) {
        return (String)getEL(expr);
    }

    public static Integer getELAsInteger(String expr) {
        return (Integer)getEL(expr);
    }

    public static Object getEL(String expr) {
        FacesContext fc = FacesContext.getCurrentInstance();
        return fc.getApplication().evaluateExpressionGet(fc, expr, Object.class);
    }

    public static Object getWithDefault(String expr, String defaultExpr) {
        Object exprVal = getEL(expr);
        return exprVal != null ? exprVal : getEL(defaultExpr);
    }

    public static void setEL(String expr, String value) {
        Object valToSet = value;
        if (isELExpr(value)) {
            valToSet = getEL(value);
        }
        setEL(expr, valToSet);
    }

    public static void setEL(String expr, Object value) {
        ELContext elc;
        ExpressionFactory ef;
        elc = getELContext();
        ef = getExpressionFactory();
        ValueExpression ve = ef.createValueExpression(elc, expr, Object.class);
        ve.setValue(elc, value);
    }

    private static boolean isELExpr(Object o) {
        if (o instanceof String) {
            String str = (String)o;
            str.trim();
            return str.startsWith("#{") && str.endsWith("}");
        }
        return false;
    }

    public static Object invokeMethod(String expr, Class[] paramTypes, Object[] params) {

        ELContext elc = getELContext();
        ExpressionFactory ef = getExpressionFactory();
        MethodExpression me = ef.createMethodExpression(elc, expr, Object.class, paramTypes);
        return me.invoke(elc, params);
    }

    public static Object invokeMethod(String expr, Class paramType, Object param) {
        return invokeMethod(expr, new Class[] { paramType }, new Object[] { param });
    }

    /**
     * Execute an AM method exposed as an operation and  bound to a page
     * definition that has two or more parameters.
     *
     * @param expr - e.g. #{bindings.amMehtod}
     * @return value if any.
     */

    public static Object invokeOperationBinding(String expr, String[] paramNames, Object[] params) {

        OperationBinding ob = (OperationBinding)getEL(expr);
        for (int i = 0; i < paramNames.length; i++) {

            ob.getParamsMap().put(paramNames[i], params[i]);
        }

        Object result = ob.execute();
        return result;
    }

    /**
     * Execute an AM method exposed as an operation and  bound to a page
     * definition that has a single parameter.
     *
     * @param expr
     * @param paramName
     * @param param
     * @return
     */
    public static Object invokeOperationBinding(String expr, String paramName, Object param) {

        Object result;

        if (!paramName.equals("")) {
            result = invokeOperationBinding(expr, new String[] { paramName }, new Object[] { param });
        } else {
            result = invokeOperationBinding(expr, new String[] { }, new Object[] { });

        }

        return result;
    }

    /**
     * Execute an AM method exposed as an operation and  bound to a page
     * definition that has no parameters.
     *
     * @param expr
     * @return
     */
    public static Object invokeOperationBinding(String expr) {

        Object result;

        result = invokeOperationBinding(expr, "", null);

        return result;
    }

    public static HttpServletRequest getRequest() {
        HttpServletRequest request = (HttpServletRequest)getFacesContext().getExternalContext().getRequest();
        return request;
    }

    public static HttpServletResponse getResponse() {
        HttpServletResponse response = (HttpServletResponse)getFacesContext().getExternalContext().getResponse();
        return response;
    }

    public static HttpSession getSession() {
        FacesContext context = getFacesContext();
        HttpSession session = (HttpSession)context.getExternalContext().getSession(false);
        return session;
    }

    /** Method to access session attributes */
    public static Object getSessionAttribute(String attributeName) {
        Object obj = getSession().getAttribute(attributeName);
        return obj;
    }

    public static void setSessionAttribute(String attributeName, Object value) {
        getSession().setAttribute(attributeName, value);
    }

    public static void removeSessionAttribute(String attributeName) {
        getSession().removeAttribute(attributeName);
    }

    public static void addAlertMessege(String alertMsg) {
        FacesContext fc = FacesContext.getCurrentInstance();
        StringBuffer alertMsgStr = new StringBuffer();
        alertMsgStr.append("alert('");
        alertMsgStr.append(alertMsg);
        alertMsgStr.append("');");
        ExtendedRenderKitService erks = Service.getService(fc.getRenderKit(), ExtendedRenderKitService.class);
        erks.addScript(fc, alertMsgStr.toString());
    }

    public static void logInfo(Logger logObject, Object info) {
        if (logObject.isInfoEnabled()) {
            logObject.info(info);
        }
    }

    public static void logDebug(Logger logObject, Object debug) {
        if (logObject.isDebugEnabled()) {
            logObject.debug(debug);
        }
    }

    /**
     * Get application module for an application module data control by name.
     * @param name application module data control name
     * @return ApplicationModule
     */
    public static ApplicationModule getApplicationModuleForDataControl(String name) {
      return (ApplicationModule)getEL("#{data."+name+".dataProvider}");
    }

    public static ApplicationModule getOnlineQuizAM() {
        return getApplicationModuleForDataControl(ONLINE_QUIZ_AM);
    }

   
//    public static void addMessageFromCode(FacesMessage.Severity type, String code) {
//        FacesContext fctx = FacesContext.getCurrentInstance();
//        String message = MessagesProperties.getPropertiesString(code);
//        FacesMessage fm = new FacesMessage(type, message, null);
//        fctx.addMessage(null, fm);
//    }

    public static Date getOracleDomainDate() {
        java.util.Date lDate = new java.util.Date();
        java.sql.Date sqlDate = new java.sql.Date(lDate.getTime());
        return (new Date(sqlDate));
    }

    public static Date getOracleDomainDateTime() {
        java.util.Date lDate = new java.util.Date();
        Timestamp ts = new java.sql.Timestamp(lDate.getTime());
        return (new Date(ts));
    }

//    public static void addMessageWithCode(FacesMessage.Severity type, String code) {
//        FacesContext fctx = FacesContext.getCurrentInstance();
//        String message = MessagesProperties.getPropertiesString(code);
//        FacesMessage fm = new FacesMessage(type, code, message);
//        fctx.addMessage(fctx.getViewRoot().getId(), fm);
//    }

    public static void addMessageWithCode(FacesMessage.Severity type, String code, String message) {
        FacesContext fctx = FacesContext.getCurrentInstance();
        FacesMessage fm = new FacesMessage(type, code, message);
        fctx.addMessage(fctx.getViewRoot().getId(), fm);
    }

//    public static void addComponentMessageWithCode(String clientCompId, FacesMessage.Severity type, String code,
//                                                   String detailMsg) {
//        FacesContext fctx = FacesContext.getCurrentInstance();
//        String message = MessagesProperties.getPropertiesString(code);
//        FacesMessage fm = new FacesMessage(type, "", message);
//        fctx.addMessage(clientCompId, fm);
//    }

    public static void addMessage(String clientCompId, FacesMessage.Severity type, String message, String detailMsg) {

        FacesContext fctx = FacesContext.getCurrentInstance();
        FacesMessage fm = new FacesMessage(type, message, detailMsg);
        fctx.addMessage(clientCompId, fm);
    }


    /**
     * This method returns an instance of GlobalInfo sessionBean
     * @return GlobalInfo
     */
    public static Object getGlobalInfo() {
        Object globalInfo = (Object)getEL("#{GlobalInfo}");
        return globalInfo;
    }

    public static Map<String, Object> getPageFlowScopeMap() {
        AdfFacesContext context = AdfFacesContext.getCurrentInstance();
        return context.getPageFlowScope();
    }
    
    public static Map<String, Object> getViewScopeMap() {
        AdfFacesContext context = AdfFacesContext.getCurrentInstance();
        return context.getViewScope();
    }

    public static Map<String, Object> getRequestScopeMap() {
        FacesContext context = FacesContext.getCurrentInstance();
        return context.getExternalContext().getRequestMap();
    }

    public static void openPopup(RichPopup popup) {

        FacesContext context = FacesContext.getCurrentInstance();
        StringBuilder script = new StringBuilder();
        script.append("var popup = AdfPage.PAGE.findComponent('").append(popup.getClientId(context)).append("'); ").append("if (!popup.isPopupVisible()) { ").append("var hints = {}; ").append("popup.show(hints);}");
        ExtendedRenderKitService erks = Service.getService(context.getRenderKit(), ExtendedRenderKitService.class);
        erks.addScript(context, script.toString());
    }

    public static void closePopup(RichPopup popup) {
        FacesContext context = FacesContext.getCurrentInstance();
        StringBuilder script = new StringBuilder();
        script.append("var popup = AdfPage.PAGE.findComponent('").append(popup.getClientId(context)).append("'); ").append("if (popup.isPopupVisible()) { ").append("var hints = {}; ").append("popup.hide(hints);}");

        ExtendedRenderKitService erks = Service.getService(context.getRenderKit(), ExtendedRenderKitService.class);
        erks.addScript(context, script.toString());
    }

    public static boolean isEmptyString(String value) {
        return ((value == null || value.length() == 0 || value.trim().length() == 0) ? true : false);
    }

    public static JUIteratorBinding getIteratorBinding(String itrName) {
        BindingContext bindingCtx = BindingContext.getCurrent();
        BindingContainer bindings = bindingCtx.getCurrentBindingsEntry();
        JUCtrlRangeBinding ctrlRangeBinding = (JUCtrlRangeBinding)bindings.getControlBinding(itrName);
        return ctrlRangeBinding.getIteratorBinding();
    }      
}
